﻿using System;
using System.Collections.Generic;

namespace Framework
{
    public static class LoaderCache
    {
        private static LinkedList<ResLoader> _LoaderList = new LinkedList<ResLoader>();
        
        private static Dictionary<ResStorageType, Func<Resource, ResLoader>> StorageTypeToLoaderMap = 
            new Dictionary<ResStorageType, Func<Resource, ResLoader>>()
            {
                {ResStorageType.Local, CreateLocalLoader},
                {ResStorageType.Remote, CreateRemoteLoader}
            };
        
        public static ResLoader Get(Resource resource)
        {
            ResLoader loader = Find(resource);
            if (loader == null)
            {
                Func<Resource, ResLoader> constructor = StorageTypeToLoaderMap[resource.storageType];
                loader = constructor(resource);
                _LoaderList.AddLast(loader);  
            }
            return loader;
        }

        public static void Release(ResLoader loader)
        {
            _LoaderList.Remove(loader);
            loader.Dispose();
        }

        public static ResLoader Find(Resource resource)
        {
            LinkedListNode<ResLoader> node = _LoaderList.First;
            while (node != null)
            {
                if (node.Value.resource == resource)
                {
                    return node.Value;
                }

                node = node.Next;
            }
            return null;
        }
        
        public static void RemoveAll()
        {
            LinkedListNode<ResLoader> node = _LoaderList.First;
            while (node != null)
            {
                ResLoader loader = node.Value;
                if (loader.isLoading)
                {
                    loader.Cancel();
                }
                loader.Dispose();
                node = node.Next;
            }
            _LoaderList.Clear();
        }
        
        private static ResLoader CreateLocalLoader(Resource resource)
        {
            return new LocalResLoader(resource);
        }

        private static ResLoader CreateRemoteLoader(Resource resource)
        {
            return new RemoteResLoader(resource);
        }
    }
}